#include "coptional.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

// 配置项元数据（自定义类型示例）
typedef struct {
    char* key;       // 配置项键名
    int line_number; // 在配置文件中的行号
    char* source;    // 来源文件名
} ConfigMeta;

// 配置项元数据的复制函数
static void config_meta_copy(const void* src, void* dest) {
    const ConfigMeta* s = (const ConfigMeta*)src;
    ConfigMeta* d = (ConfigMeta*)dest;
    
    d->line_number = s->line_number;
    
    // 复制字符串
    if (s->key) {
        d->key = (char*)malloc(strlen(s->key) + 1);
        strcpy(d->key, s->key);
    } else {
        d->key = NULL;
    }
    
    if (s->source) {
        d->source = (char*)malloc(strlen(s->source) + 1);
        strcpy(d->source, s->source);
    } else {
        d->source = NULL;
    }
}

// 配置项元数据的销毁函数
static void config_meta_destroy(void* data) {
    ConfigMeta* meta = (ConfigMeta*)data;
    if (meta->key) free(meta->key);
    if (meta->source) free(meta->source);
}

// 配置存储结构
typedef struct {
    char** keys;               // 键列表
    COptional** values;        // 值列表（使用coptional存储）
    COptional** metas;         // 元数据列表（自定义类型）
    int count;                 // 配置项数量
    int capacity;              // 容量
} ConfigStore;

// 初始化配置存储
static ConfigStore* config_store_init(int initial_capacity) {
    ConfigStore* store = (ConfigStore*)malloc(sizeof(ConfigStore));
    if (!store) return NULL;
    
    store->count = 0;
    store->capacity = initial_capacity > 0 ? initial_capacity : 10;
    store->keys = (char**)malloc(sizeof(char*) * store->capacity);
    store->values = (COptional**)malloc(sizeof(COptional*) * store->capacity);
    store->metas = (COptional**)malloc(sizeof(COptional*) * store->capacity);
    
    if (!store->keys || !store->values || !store->metas) {
        free(store->keys);
        free(store->values);
        free(store->metas);
        free(store);
        return NULL;
    }
    
    return store;
}

// 释放配置存储
static void config_store_free(ConfigStore* store) {
    if (!store) return;
    
    for (int i = 0; i < store->count; i++) {
        free(store->keys[i]);
        coptional_destroy(store->values[i]);
        coptional_destroy(store->metas[i]);
    }
    
    free(store->keys);
    free(store->values);
    free(store->metas);
    free(store);
}

// 扩展配置存储容量
static int config_store_resize(ConfigStore* store) {
    if (!store) return -1;
    
    int new_capacity = store->capacity * 2;
    char** new_keys = (char**)realloc(store->keys, sizeof(char*) * new_capacity);
    COptional** new_values = (COptional**)realloc(store->values, sizeof(COptional*) * new_capacity);
    COptional** new_metas = (COptional**)realloc(store->metas, sizeof(COptional*) * new_capacity);
    
    if (!new_keys || !new_values || !new_metas) return -1;
    
    store->keys = new_keys;
    store->values = new_values;
    store->metas = new_metas;
    store->capacity = new_capacity;
    return 0;
}

// 添加配置项
static int config_store_add(ConfigStore* store, const char* key, COptional* value, COptional* meta) {
    if (!store || !key || !value || !meta) return -1;
    
    // 需要时扩容
    if (store->count >= store->capacity && config_store_resize(store) != 0) {
        return -1;
    }
    
    // 存储键
    store->keys[store->count] = (char*)malloc(strlen(key) + 1);
    if (!store->keys[store->count]) return -1;
    strcpy(store->keys[store->count], key);
    
    // 存储值和元数据
    store->values[store->count] = value;
    store->metas[store->count] = meta;
    store->count++;
    
    return 0;
}

// 查找配置项索引
static int config_store_find_index(const ConfigStore* store, const char* key) {
    if (!store || !key) return -1;
    
    for (int i = 0; i < store->count; i++) {
        if (strcmp(store->keys[i], key) == 0) {
            return i;
        }
    }
    return -1;
}

// 去除字符串首尾空格
static char* trim(char* str) {
    if (!str) return NULL;
    
    // 去除开头空格
    while (isspace((unsigned char)*str)) str++;
    
    // 去除结尾空格
    if (*str) {
        char* end = str + strlen(str) - 1;
        while (end > str && isspace((unsigned char)*end)) end--;
        *(end + 1) = '\0';
    }
    
    return str;
}

// 解析配置文件
static ConfigStore* parse_config_file(const char* filename) {
    FILE* file = fopen(filename, "r");
    if (!file) {
        fprintf(stderr, "无法打开配置文件: %s\n", filename);
        return NULL;
    }
    
    ConfigStore* store = config_store_init(10);
    if (!store) {
        fclose(file);
        return NULL;
    }
    
    // 注册自定义类型：配置项元数据
    COptionalType meta_type = coptional_register_custom_type(
        sizeof(ConfigMeta),
        config_meta_copy,
        config_meta_destroy
    );
    
    char line[1024];
    int line_number = 0;
    
    while (fgets(line, sizeof(line), file)) {
        line_number++;
        char* content = trim(line);
        
        // 跳过空行和注释
        if (*content == '\0' || *content == '#' || *content == ';') {
            continue;
        }
        
        // 查找键值分隔符
        char* eq_pos = strchr(content, '=');
        if (!eq_pos) {
            fprintf(stderr, "警告: 无效行 %d，跳过: %s\n", line_number, content);
            continue;
        }
        
        // 分割键和值
        *eq_pos = '\0';
        char* key = trim(content);
        char* value_str = trim(eq_pos + 1);
        
        if (*key == '\0') {
            fprintf(stderr, "警告: 无效键（行 %d），跳过\n", line_number);
            continue;
        }
        
        // 解析值并存储到coptional
        COptional* value = coptional_create();
        if (!value) continue;
        
        // 尝试解析为整数
        char* endptr;
        long int_val = strtol(value_str, &endptr, 10);
        if (*endptr == '\0') {
            coptional_set_int(value, (int)int_val);
        }
        // 尝试解析为浮点数
        else {
            double double_val = strtod(value_str, &endptr);
            if (*endptr == '\0') {
                coptional_set_double(value, double_val);
            }
            // 视为字符串
            else {
                coptional_set_str(value, value_str);
            }
        }
        
        // 创建元数据
        ConfigMeta meta_data;
        meta_data.key = (char*)key;  // 临时指向，会在copy中复制
        meta_data.line_number = line_number;
        meta_data.source = (char*)filename;  // 临时指向
        
        COptional* meta = coptional_create();
        if (meta) {
            coptional_set_custom(meta, meta_type, &meta_data);
        }
        
        // 添加到配置存储
        config_store_add(store, key, value, meta);
    }
    
    fclose(file);
    return store;
}

// 显示配置项信息
static void print_config_value(const char* key, const COptional* value, const COptional* meta) {
    if (!key || !value) return;
    
    printf("%s = ", key);
    
    // 打印值
    if (!coptional_has_value(value)) {
        printf("(无值)\n");
        return;
    }
    
    switch (coptional_get_type(value)) {
        case COPTIONAL_INT:
            printf("%d (整数)\n", coptional_get_int(value, 0));
            break;
        case COPTIONAL_FLOAT:
            printf("%f (浮点数)\n", coptional_get_float(value, 0.0f));
            break;
        case COPTIONAL_DOUBLE:
            printf("%f (双精度浮点数)\n", coptional_get_double(value, 0.0));
            break;
        case COPTIONAL_STR:
            printf("\"%s\" (字符串)\n", coptional_get_str(value, ""));
            break;
        default:
            printf("(未知类型)\n");
    }
    
    // 打印元数据（如果存在）
    if (coptional_has_value(meta)) {
        ConfigMeta meta_data;
        if (coptional_get_custom(meta, &meta_data) == 0) {
            printf("  来源: %s (行 %d)\n", 
                   meta_data.source ? meta_data.source : "未知",
                   meta_data.line_number);
        }
    }
}

// 显示帮助信息
static void print_help(const char* progname) {
    printf("配置文件解析工具（使用coptional库）\n");
    printf("用法:\n");
    printf("  %s <配置文件>               - 列出所有配置项\n", progname);
    printf("  %s <配置文件> <键名>        - 查询指定配置项\n", progname);
    printf("  %s <配置文件> <键名> <默认值> - 查询配置项，不存在则返回默认值\n", progname);
    printf("示例:\n");
    printf("  %s config.ini               - 列出config.ini中所有配置项\n", progname);
    printf("  %s config.ini port          - 查询port配置项\n", progname);
    printf("  %s config.ini timeout 30    - 查询timeout，默认30\n", progname);
}

int main(int argc, char* argv[]) {
    // 检查命令行参数
    if (argc < 2) {
        print_help(argv[0]);
        return 1;
    }
    
    // 解析配置文件
    ConfigStore* config = parse_config_file(argv[1]);
    if (!config) {
        return 1;
    }
    
    // 处理不同模式
    if (argc == 2) {
        // 列出所有配置项
        printf("配置文件: %s，共 %d 项\n", argv[1], config->count);
        for (int i = 0; i < config->count; i++) {
            print_config_value(config->keys[i], config->values[i], config->metas[i]);
        }
    }
    else if (argc == 3) {
        // 查询指定配置项
        const char* key = argv[2];
        int index = config_store_find_index(config, key);
        
        if (index != -1) {
            print_config_value(key, config->values[index], config->metas[index]);
        } else {
            printf("配置项 '%s' 不存在\n", key);
            config_store_free(config);
            return 1;
        }
    }
    else if (argc == 4) {
        // 查询配置项，带默认值
        const char* key = argv[2];
        const char* default_val = argv[3];
        int index = config_store_find_index(config, key);
        
        if (index != -1) {
            print_config_value(key, config->values[index], config->metas[index]);
        } else {
            printf("%s = %s (默认值)\n", key, default_val);
        }
    }
    else {
        print_help(argv[0]);
        config_store_free(config);
        return 1;
    }
    
    // 清理资源
    config_store_free(config);
    return 0;
}
